package com.cui.project.controller;
import java.util.Date;


import com.api.common.common.BaseResponse;
import com.api.common.common.ErrorCode;
import com.api.common.common.ResultUtils;
import com.api.common.model.entity.InterfaceInfo;
import com.api.common.model.entity.User;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cui.project.annotation.AuthCheck;
import com.cui.project.constant.UserConstant;
import com.cui.project.exception.BusinessException;
import com.cui.project.model.dto.trafficForecast.TrafficForecastQueryRequest;
import com.cui.project.model.entity.InterfaceTrafficForecast;
import com.cui.project.model.entity.InterfaceTrafficMetrics;
import com.cui.project.model.entity.UserInterfaceTrafficForecast;
import com.cui.project.model.entity.UserInterfaceTrafficMetrics;
import com.cui.project.model.enums.ForecastModelTypeEnum;
import com.cui.project.model.enums.ForecastQueryTypeEnum;
import com.cui.project.model.enums.ForecastTimeGranularityEnum;
import com.cui.project.model.vo.TrafficForecastChartVO;
import com.cui.project.model.vo.TrafficForecastVo;
import com.cui.project.service.*;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.repository.query.Param;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 流量预测可视化控制器
 *
 * 功能：
 * 1. 查询历史流量数据
 * 2. 查询预测流量数据
 * 3. 获取流量趋势图表数据（历史+预测）
 * 4. 获取热门接口预测排行
 * 5. 获取流量统计摘要
 *
 * @author cui
 * @date 2025-11-04
 */
@RestController
@RequestMapping("/traffic/forecast")
@Slf4j
public class TrafficForecastController {

    @Resource
    private InterfaceInfoService interfaceInfoService;

    @Resource
    private InterfaceTrafficMetricsService metricsService;

    @Resource
    private InterfaceTrafficForecastService forecastService;

    @Resource
    private UserInterfaceTrafficMetricsService  userInterfaceTrafficMetricsService;

    @Resource
    private UserInterfaceTrafficForecastService userInterfaceTrafficForecastService;

    @Resource
    private UserService userService;

    private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    private final SimpleDateFormat sdf_hh_mm = new SimpleDateFormat("HH:mm");


    /**
     * 获取流量预测图表数据（历史 + 预测）
     *
     * 适用场景：前端图表展示（ECharts、AntV G2 等）
     * 返回格式：时间序列数据，包含历史和预测两部分
     *
     * @param request 查询请求
     * @return 图表数据
     */
    @PostMapping("/chart")

    public BaseResponse<TrafficForecastChartVO> getTrafficForecastChart(@RequestBody TrafficForecastQueryRequest queryRequest,
                                                                        @RequestParam Integer type,
                                                                        HttpServletRequest request){
        //1.参数校验
        if(queryRequest==null||queryRequest.getInterfaceId()==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"接口id不能为空");
        }
        
        AnalysisTypeEnum analysisEnum = AnalysisTypeEnum.get(type);
        if(analysisEnum==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"未知 type="+type);
        }

        String queryType = queryRequest.getQueryType();
        boolean boolQT=StringUtils.isNotBlank(queryType);
        ForecastQueryTypeEnum typeEnum = ForecastQueryTypeEnum.get(queryType);
        if(boolQT&&typeEnum==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"未知预测查询类型，query="+queryType);
        }

        String timeGranularity = queryRequest.getTimeGranularity();
        boolean boolTG=StringUtils.isNotBlank(timeGranularity);
        if(boolTG){
            ForecastTimeGranularityEnum granularityEnum = ForecastTimeGranularityEnum.get(timeGranularity);
            if(granularityEnum==null){
                throw new BusinessException(ErrorCode.PARAMS_ERROR,"未知预测时间粒度类型，time="+timeGranularity);
            }
        }

        String modelType = queryRequest.getModelType();
        boolean boolMT=StringUtils.isNotBlank(modelType);
        if(boolMT){
            ForecastModelTypeEnum modelTypeEnum = ForecastModelTypeEnum.get(modelType);
            if(modelTypeEnum==null){
                throw new BusinessException(ErrorCode.PARAMS_ERROR,"未知预测模型类型，model="+modelType);
            }
        }

        Long interfaceId = queryRequest.getInterfaceId();
        InterfaceInfo interfaceInfo = interfaceInfoService.getById(interfaceId);
        if(interfaceInfo==null){
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"接口不存在");
        }

        User user = userService.getLoginUser(request);


        //2.设置查询时间范围
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startTime=queryRequest.getStartTime()!=null?LocalDateTime.ofInstant(queryRequest.getStartTime().toInstant(), ZoneId.systemDefault())
                :now.minus(7, ChronoUnit.DAYS); // 默认查询最近7天
        LocalDateTime endTime=queryRequest.getEndTime()!=null?LocalDateTime.ofInstant(queryRequest.getEndTime().toInstant(), ZoneId.systemDefault())
                :now.plus(1, ChronoUnit.DAYS);// 默认预测未来1天

        TrafficForecastChartVO chartVO =null;


        if(AnalysisTypeEnum.use.type.equals(type)){
            if(!interfaceInfoService.isInfo(user.getId(), interfaceId)){
                throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"当前用户未上传过此接口");
            }

            //3. 查询历史流量数据（当前到前7天等）
            LambdaQueryWrapper<UserInterfaceTrafficMetrics> metricsLambdaQueryWrapper = new LambdaQueryWrapper<>();
            metricsLambdaQueryWrapper.eq(UserInterfaceTrafficMetrics::getInterfaceInfoId,interfaceId);
            metricsLambdaQueryWrapper.between(UserInterfaceTrafficMetrics::getTimeBucket,
                    Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),
                    Date.from(now.atZone(ZoneId.systemDefault()).toInstant())
            );
            metricsLambdaQueryWrapper.orderByAsc(UserInterfaceTrafficMetrics::getTimeBucket);
            List<UserInterfaceTrafficMetrics> historicalData =null;
            if(boolQT&&(ForecastQueryTypeEnum.ALL.getName().equals(typeEnum.getName())||
                    ForecastQueryTypeEnum.HISTORICAL.equals(typeEnum.getName()))){
                historicalData=userInterfaceTrafficMetricsService.list(metricsLambdaQueryWrapper);
            }

            //4.查询预测数据（当前时间到后1天等）
            LambdaQueryWrapper<UserInterfaceTrafficForecast> forecastQuery= new LambdaQueryWrapper<>();
            forecastQuery.eq(UserInterfaceTrafficForecast::getInterfaceInfoId,interfaceId);
            forecastQuery.between(UserInterfaceTrafficForecast::getForecastTime,
                    Date.from(now.atZone(ZoneId.systemDefault()).toInstant()),
                    Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant())
            );
            //如果指定了模型类型，按模型类型过滤
            forecastQuery.eq(boolMT,UserInterfaceTrafficForecast::getModelType,modelType);

            forecastQuery.orderByAsc(UserInterfaceTrafficForecast::getForecastTime);
            List<UserInterfaceTrafficForecast> forecastData=null;
            if(boolQT&&(ForecastQueryTypeEnum.ALL.getName().equals(typeEnum.getName())||
                    ForecastQueryTypeEnum.FORECAST.equals(typeEnum.getName()))){
                forecastData=userInterfaceTrafficForecastService.list(forecastQuery);
            }

            // 6. 构造图表数据
            chartVO= buildUserInterfaceChartData(
                    interfaceInfo,
                    historicalData==null?Collections.emptyList():historicalData,
                    forecastData==null?Collections.emptyList():forecastData,
                    queryRequest.getIncludeConfidence() != null && queryRequest.getIncludeConfidence()
            );

        }else{

            if( AnalysisTypeEnum.all.getType().equals(type)){
                if(!userService.isAdmin(request)){
                    throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
                }
            }else{
                if(!interfaceInfoService.isInfo(user.getId(), interfaceId)){
                    throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"当前用户未上传过此接口");
                }
            }

            //3. 查询历史流量数据（当前到前7天等）
            LambdaQueryWrapper<InterfaceTrafficMetrics> metricsQuery= new LambdaQueryWrapper<>();
            metricsQuery.eq(InterfaceTrafficMetrics::getInterfaceInfoId,interfaceId);
            metricsQuery.between(InterfaceTrafficMetrics::getTimeBucket,
                    Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),
                    Date.from(now.atZone(ZoneId.systemDefault()).toInstant())
            );

            metricsQuery.orderByAsc(InterfaceTrafficMetrics::getTimeBucket);
            List<InterfaceTrafficMetrics> historicalData =null;
            if(boolQT&&(ForecastQueryTypeEnum.ALL.getName().equals(typeEnum.getName())||
                    ForecastQueryTypeEnum.HISTORICAL.equals(typeEnum.getName()))){
                historicalData=metricsService.list(metricsQuery);
            }


            //4.查询预测数据（当前时间到后1天等）
            LambdaQueryWrapper<InterfaceTrafficForecast> forecastQuery= new LambdaQueryWrapper<>();
            forecastQuery.eq(InterfaceTrafficForecast::getInterfaceInfoId,interfaceId);
            forecastQuery.between(InterfaceTrafficForecast::getForecastTime,
                    Date.from(now.atZone(ZoneId.systemDefault()).toInstant()),
                    Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant())
            );
            //如果指定了模型类型，按模型类型过滤
            forecastQuery.eq(boolMT,InterfaceTrafficForecast::getModelType,modelType);

            forecastQuery.orderByAsc(InterfaceTrafficForecast::getForecastTime);
            List<InterfaceTrafficForecast> forecastData=null;
            if(boolQT&&(ForecastQueryTypeEnum.ALL.getName().equals(typeEnum.getName())||
                    ForecastQueryTypeEnum.FORECAST.equals(typeEnum.getName()))){
                forecastData=forecastService.list(forecastQuery);
            }

            // 6. 构造图表数据
            chartVO= buildChartData(
                    interfaceInfo,
                    historicalData==null?Collections.emptyList():historicalData,
                    forecastData==null?Collections.emptyList():forecastData,
                    queryRequest.getIncludeConfidence() != null && queryRequest.getIncludeConfidence()
            );
        }

        return ResultUtils.success(chartVO);
    }


    /**
     * 获取热门接口预测排行
     *
     * 适用场景：首页Dashboard展示
     * 展示内容：预测流量最高的Top N个接口
     *
     * @param topN 返回前N个（默认10）
     * @param hours 预测时段（默认24小时）
     * @return 热门接口列表
     */
    @GetMapping("/top")
    public BaseResponse<List<TrafficForecastVo>> getTopForecastInterfaces(
            @RequestParam(defaultValue = "10") Integer topN,
            @RequestParam(defaultValue = "24")Integer hours,
            @RequestParam Integer type,
            HttpServletRequest request
    ){
        AnalysisTypeEnum analysisEnum = AnalysisTypeEnum.get(type);
        if(analysisEnum==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"未知，type="+type);
        }

        User user = userService.getLoginUser(request);
        Long userId = user.getId();

        // 1. 计算查询时间范围
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startTime=now;
        LocalDateTime endTime = now.plus(hours, ChronoUnit.HOURS);

        ArrayList<TrafficForecastVo> result = new ArrayList<>();
        if(AnalysisTypeEnum.use.getType().equals(type)){
            List<Long> ids = interfaceInfoService.useInterfaceIds(userId);
            if(ids.isEmpty()){
                return ResultUtils.success(Collections.emptyList());
            }

            // 2. 查询所有接口的预测数据
            LambdaQueryWrapper<UserInterfaceTrafficForecast> forecastQuery= new LambdaQueryWrapper<>();
            forecastQuery.in(UserInterfaceTrafficForecast::getInterfaceInfoId,ids);
            forecastQuery.between(UserInterfaceTrafficForecast::getForecastTime,
                    Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),
                    Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant())
            );
            forecastQuery.orderByDesc(UserInterfaceTrafficForecast::getForecastTime);
            List<UserInterfaceTrafficForecast> forecasts = userInterfaceTrafficForecastService.list(forecastQuery);

            if(forecasts.isEmpty()){
                return ResultUtils.success(Collections.emptyList());
            }

            // 3. 按接口ID分组，计算每个接口的总预测流量
            Map<Long, Integer>  interfaceTrafficMap=forecasts.stream()
                    .collect(Collectors.groupingBy(
                            UserInterfaceTrafficForecast::getInterfaceInfoId,
                            Collectors.summingInt(UserInterfaceTrafficForecast::getForecastRequestCount)
                    ));

            // 4. 排序并获取Top N
            List<Map.Entry<Long, Integer>> topInterfaces = interfaceTrafficMap.entrySet().stream()
                    .sorted(Map.Entry.<Long, Integer>comparingByValue().reversed())
                    .limit(topN)
                    .collect(Collectors.toList());

            // 5. 查询接口详细信息并构造VO
            Set<Long> idSets = interfaceTrafficMap.keySet().stream().collect(Collectors.toSet());
            List<InterfaceInfo> interfaceInfos = interfaceInfoService.listByIds(idSets);
            for (InterfaceInfo interfaceInfo : interfaceInfos) {

                Long interfaceInfoId = interfaceInfo.getId();

                Map.Entry<Long, Integer> entry = topInterfaces.stream()
                        .filter(t -> t.getKey().equals(interfaceInfoId))
                        .findFirst()
                        .orElse(null);
                if(entry==null) continue;

                // 获取该接口最新的预测记录（用于获取模型信息）
                UserInterfaceTrafficForecast latestForecast = forecasts.stream()
                        .filter(f -> f.getInterfaceInfoId().equals(interfaceInfo.getId()))
                        .findFirst()
                        .orElse(null);

                TrafficForecastVo vo = new TrafficForecastVo();
                vo.setInterfaceInfoId(interfaceInfoId);
                vo.setInterfaceName(interfaceInfo.getName());
                vo.setPredictedRequestCount(entry.getValue());
                vo.setTimeLabel(sdf.format(endTime));
                vo.setDataType("forecast");

                if(latestForecast!=null){
                    vo.setModelType(latestForecast.getModelType());
                    vo.setAccuracyScore(latestForecast.getAccuracyScore());
                    vo.setConfidenceLower(vo.getConfidenceLower());
                    vo.setConfidenceUpper(vo.getConfidenceUpper());
                }
                result.add(vo);
            }
        }else{
            if(AnalysisTypeEnum.all.getType().equals(type)){
                if (!userService.isAdmin(request)) {
                    throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
                }
            }
            // 2. 查询所有接口的预测数据
            LambdaQueryWrapper<InterfaceTrafficForecast> forecastQuery= new LambdaQueryWrapper<>();

            //如果type=1，说明是查询用户上传接口的预测数据，不是就是管理员查询全部
            if(AnalysisTypeEnum.upload.getType().equals(type)){
                LambdaQueryWrapper<InterfaceInfo> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(InterfaceInfo::getUserId,userId);
                queryWrapper.select(InterfaceInfo::getId);
                List<Long> ids = interfaceInfoService.listObjs(queryWrapper).stream().map(ii -> {
                    return (Long) ii;
                }).collect(Collectors.toList());
                forecastQuery.in(InterfaceTrafficForecast::getInterfaceInfoId,ids);
            }

            forecastQuery.between(InterfaceTrafficForecast::getForecastTime,
                    Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),
                    Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant())
            );
            forecastQuery.orderByDesc(InterfaceTrafficForecast::getForecastTime);
            List<InterfaceTrafficForecast> forecasts = forecastService.list(forecastQuery);

            if(forecasts.isEmpty()){
                return ResultUtils.success(Collections.emptyList());
            }

            // 3. 按接口ID分组，计算每个接口的总预测流量
            Map<Long, Integer> interfaceTrafficMap=forecasts.stream()
                    .collect(Collectors.groupingBy(
                            InterfaceTrafficForecast::getInterfaceInfoId,
                            Collectors.summingInt(InterfaceTrafficForecast::getForecastRequestCount)
                    ));

            // 4. 排序并获取Top N
            List<Map.Entry<Long, Integer>> topInterfaces = interfaceTrafficMap.entrySet().stream()
                    .sorted(Map.Entry.<Long, Integer>comparingByValue().reversed())
                    .limit(topN)
                    .collect(Collectors.toList());

            // 5. 查询接口详细信息并构造VO
            Set<Long> idSets = interfaceTrafficMap.keySet().stream().collect(Collectors.toSet());
            List<InterfaceInfo> interfaceInfos = interfaceInfoService.listByIds(idSets);
            for (InterfaceInfo interfaceInfo : interfaceInfos) {

                Long interfaceInfoId = interfaceInfo.getId();

                Map.Entry<Long, Integer> entry = topInterfaces.stream()
                        .filter(t -> t.getKey().equals(interfaceInfoId))
                        .findFirst()
                        .orElse(null);
                if(entry==null) continue;

                // 获取该接口最新的预测记录（用于获取模型信息）
                InterfaceTrafficForecast latestForecast = forecasts.stream()
                        .filter(f -> f.getInterfaceInfoId().equals(interfaceInfo.getId()))
                        .findFirst()
                        .orElse(null);

                TrafficForecastVo vo = new TrafficForecastVo();
                vo.setInterfaceInfoId(interfaceInfoId);
                vo.setInterfaceName(interfaceInfo.getName());
                vo.setPredictedRequestCount(entry.getValue());
                vo.setTimeLabel(sdf.format(endTime));
                vo.setDataType("forecast");

                if(latestForecast!=null){
                    vo.setModelType(latestForecast.getModelType());
                    vo.setAccuracyScore(latestForecast.getAccuracyScore());
                    vo.setConfidenceLower(vo.getConfidenceLower());
                    vo.setConfidenceUpper(vo.getConfidenceUpper());
                }
                result.add(vo);
            }
        }



        return ResultUtils.success(result);
    }

    /**
     * 获取指定接口的流量统计摘要
     *
     * 适用场景：接口详情页的统计卡片
     * 展示内容：平均流量、峰值、增长率等关键指标
     *
     * @param interfaceId 接口ID
     * @param days 统计天数（默认7天）
     * @return 统计摘要
     */
    @GetMapping("/summary/{interfaceId}")
    public BaseResponse<TrafficForecastChartVO.TrafficSummary> getTrafficSummary(
            @PathVariable Long interfaceId,
            @RequestParam(defaultValue = "7") Integer days,
            @RequestParam Integer type,
            HttpServletRequest request
    ){
        AnalysisTypeEnum analysisEnum = AnalysisTypeEnum.get(type);
        if(analysisEnum==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"未知，type="+type);
        }

        //1.校验参数
        if(interfaceId==null||interfaceId<=0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if(days<=0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        User user = userService.getLoginUser(request);
        Long userId = user.getId();

        InterfaceInfo interfaceInfo = interfaceInfoService.getById(interfaceId);
        if(interfaceInfo==null){
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"接口不存在");
        }

        //2.查询历史数据
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startTime = now.minus(days, ChronoUnit.DAYS);


        // 4. 计算统计指标
        TrafficForecastChartVO.TrafficSummary summary = new TrafficForecastChartVO.TrafficSummary();
        if(AnalysisTypeEnum.use.getType().equals(type)){
            List<Long> ids = interfaceInfoService.useInterfaceIds(userId);
            if(ids.isEmpty()){
                return ResultUtils.success(new TrafficForecastChartVO.TrafficSummary());
            }

            LambdaQueryWrapper<UserInterfaceTrafficMetrics> metricsLambdaQueryWrapper = new LambdaQueryWrapper<>();
            metricsLambdaQueryWrapper.in(UserInterfaceTrafficMetrics::getInterfaceInfoId,ids);
            metricsLambdaQueryWrapper.eq(UserInterfaceTrafficMetrics::getInterfaceInfoId,interfaceId);
            metricsLambdaQueryWrapper.between(UserInterfaceTrafficMetrics::getTimeBucket,
                    Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),
                    Date.from(now.atZone(ZoneId.systemDefault()).toInstant())
            );
            List<UserInterfaceTrafficMetrics> historicalData = userInterfaceTrafficMetricsService.list(metricsLambdaQueryWrapper);

            //3.查询预测数据
            LocalDateTime forecastEnd = now.plus(days, ChronoUnit.DAYS);
            LambdaQueryWrapper<UserInterfaceTrafficForecast> forecastLambdaQueryWrapper = new LambdaQueryWrapper<>();
            forecastLambdaQueryWrapper.in(UserInterfaceTrafficForecast::getInterfaceInfoId,ids);
            forecastLambdaQueryWrapper.eq(UserInterfaceTrafficForecast::getInterfaceInfoId,interfaceId);
            forecastLambdaQueryWrapper.between(UserInterfaceTrafficForecast::getForecastTime,
                    Date.from(now.atZone(ZoneId.systemDefault()).toInstant()),
                    Date.from(forecastEnd.atZone(ZoneId.systemDefault()).toInstant())
            );
            List<UserInterfaceTrafficForecast> forecastData = userInterfaceTrafficForecastService.list(forecastLambdaQueryWrapper);

            // 历史平均流量
            double avgHistorical = historicalData.stream()
                    .mapToInt(UserInterfaceTrafficMetrics::getRequestCount)
                    .average()
                    .orElse(0.0);
            summary.setAvgHistorical(BigDecimal.valueOf(avgHistorical).setScale(2,RoundingMode.HALF_UP).doubleValue());

            // 历史最大流量
            int maxHistorical = historicalData.stream()
                    .mapToInt(UserInterfaceTrafficMetrics::getRequestCount)
                    .max()
                    .orElse(0);
            summary.setMaxHistorical(maxHistorical);

            // 预测平均流量
            double avgForecast = forecastData.stream()
                    .mapToInt(UserInterfaceTrafficForecast::getForecastRequestCount)
                    .average()
                    .orElse(0.0);
            summary.setAvgForecast(BigDecimal.valueOf(avgForecast).setScale(2,RoundingMode.HALF_UP).doubleValue());



            Optional<UserInterfaceTrafficForecast> max = forecastData.stream()
                    .max(Comparator.comparingInt(UserInterfaceTrafficForecast::getForecastRequestCount));
            max.ifPresent(f->{
                // 预测最大流量
                summary.setMaxForecast(f.getForecastRequestCount());
                // 预测峰值时间
                summary.setPeakTime(sdf.format(f.getForecastTime()));
            });

            // 流量增长率
            if (avgHistorical > 0) {
                double growthRate = ((avgForecast - avgHistorical) / avgHistorical) * 100;
                summary.setGrowthRate(BigDecimal.valueOf(growthRate).setScale(2, RoundingMode.HALF_UP).doubleValue());
            } else {
                summary.setGrowthRate(0.0);
            }
        }else{
            if(AnalysisTypeEnum.all.getType().equals(type)&&!userService.isAdmin(request)){
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
            }else if(!interfaceInfoService.isInfo(userId,interfaceId)){
                    throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"当前用户未上传过此接口");
            }

            LambdaQueryWrapper<InterfaceTrafficMetrics> metricsLambdaQueryWrapper = new LambdaQueryWrapper<>();
            metricsLambdaQueryWrapper.eq(InterfaceTrafficMetrics::getInterfaceInfoId,interfaceId);
            metricsLambdaQueryWrapper.between(InterfaceTrafficMetrics::getTimeBucket,
                    Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),
                    Date.from(now.atZone(ZoneId.systemDefault()).toInstant())
            );
            List<InterfaceTrafficMetrics> historicalData = metricsService.list(metricsLambdaQueryWrapper);

            //3.查询预测数据
            LocalDateTime forecastEnd = now.plus(days, ChronoUnit.DAYS);
            LambdaQueryWrapper<InterfaceTrafficForecast> forecastLambdaQueryWrapper = new LambdaQueryWrapper<>();
            forecastLambdaQueryWrapper.eq(InterfaceTrafficForecast::getInterfaceInfoId,interfaceId);
            forecastLambdaQueryWrapper.between(InterfaceTrafficForecast::getForecastTime,
                    Date.from(now.atZone(ZoneId.systemDefault()).toInstant()),
                    Date.from(forecastEnd.atZone(ZoneId.systemDefault()).toInstant())
            );
            List<InterfaceTrafficForecast> forecastData = forecastService.list(forecastLambdaQueryWrapper);

            // 历史平均流量
            double avgHistorical = historicalData.stream()
                    .mapToInt(InterfaceTrafficMetrics::getRequestCount)
                    .average()
                    .orElse(0.0);
            summary.setAvgHistorical(BigDecimal.valueOf(avgHistorical).setScale(2,RoundingMode.HALF_UP).doubleValue());

            // 历史最大流量
            int maxHistorical = historicalData.stream()
                    .mapToInt(InterfaceTrafficMetrics::getRequestCount)
                    .max()
                    .orElse(0);
            summary.setMaxHistorical(maxHistorical);

            // 预测平均流量
            double avgForecast = forecastData.stream()
                    .mapToInt(InterfaceTrafficForecast::getForecastRequestCount)
                    .average()
                    .orElse(0.0);
            summary.setAvgForecast(BigDecimal.valueOf(avgForecast).setScale(2,RoundingMode.HALF_UP).doubleValue());



            Optional<InterfaceTrafficForecast> max = forecastData.stream()
                    .max(Comparator.comparingInt(InterfaceTrafficForecast::getForecastRequestCount));
            max.ifPresent(f->{
                // 预测最大流量
                summary.setMaxForecast(f.getForecastRequestCount());
                // 预测峰值时间
                summary.setPeakTime(sdf.format(f.getForecastTime()));
            });

            // 流量增长率
            if (avgHistorical > 0) {
                double growthRate = ((avgForecast - avgHistorical) / avgHistorical) * 100;
                summary.setGrowthRate(BigDecimal.valueOf(growthRate).setScale(2, RoundingMode.HALF_UP).doubleValue());
            } else {
                summary.setGrowthRate(0.0);
            }
        }

        return ResultUtils.success(summary);
    }

    /**
     * 获取实时流量监控数据（最近1小时）
     *
     * 适用场景：实时监控页面
     * 展示内容：最近1小时的实际流量 vs 预测流量
     *
     * @param interfaceId 接口ID（可选，不传则返回所有接口）
     * @return 实时监控数据
     */
    @GetMapping("/realtime")

    public BaseResponse<List<TrafficForecastVo>> getRealtimeTraffic(
            @RequestParam(required = false) Long interfaceId,
            @RequestParam Integer type,
            HttpServletRequest request
    ){

        AnalysisTypeEnum analysisEnum = AnalysisTypeEnum.get(type);
        if(analysisEnum==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"未知，type="+type);
        }

        User user = userService.getLoginUser(request);
        Long userId = user.getId();

        // 1. 计算查询时间范围（最近1小时）
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startTime = now.minus(1, ChronoUnit.HOURS);

        // 4. 构造对比数据
        ArrayList<TrafficForecastVo> result = new ArrayList<>();
        if(AnalysisTypeEnum.use.type.equals(type)){
            List<Long> ids = interfaceInfoService.useInterfaceIds(userId);
            if(ids.isEmpty()){
                return ResultUtils.success(result);
            }
            // 2. 查询实际流量
            LambdaQueryWrapper<UserInterfaceTrafficMetrics> metricsLambdaQueryWrapper = new LambdaQueryWrapper<>();
            if(interfaceId!=null){
                metricsLambdaQueryWrapper.eq(UserInterfaceTrafficMetrics::getInterfaceInfoId,interfaceId);
            }
            metricsLambdaQueryWrapper.in(UserInterfaceTrafficMetrics::getInterfaceInfoId,ids);
            metricsLambdaQueryWrapper.between(UserInterfaceTrafficMetrics::getTimeBucket,
                    Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),
                    Date.from(now.atZone(ZoneId.systemDefault()).toInstant())
            );
            metricsLambdaQueryWrapper.orderByDesc(UserInterfaceTrafficMetrics::getTimeBucket);
            List<UserInterfaceTrafficMetrics> actualData = userInterfaceTrafficMetricsService.list(metricsLambdaQueryWrapper);

            // 3. 查询预测数据
            LambdaQueryWrapper<UserInterfaceTrafficForecast> forecastLambdaQueryWrapper = new LambdaQueryWrapper<>();
            if(interfaceId!=null){
                forecastLambdaQueryWrapper.eq(UserInterfaceTrafficForecast::getInterfaceInfoId,interfaceId);
            }
            forecastLambdaQueryWrapper.in(UserInterfaceTrafficForecast::getInterfaceInfoId,ids);
            forecastLambdaQueryWrapper.between(UserInterfaceTrafficForecast::getForecastTime,
                    Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),
                    Date.from(now.atZone(ZoneId.systemDefault()).toInstant())
            );
            forecastLambdaQueryWrapper.orderByDesc(UserInterfaceTrafficForecast::getForecastTime);
            List<UserInterfaceTrafficForecast> forecastData = userInterfaceTrafficForecastService.list(forecastLambdaQueryWrapper);

            // 构造时间-实际流量映射
            Map<String, Map<Long, UserInterfaceTrafficMetrics>> actualMap = actualData.stream()
                    .collect(Collectors.groupingBy(
                            m -> sdf_hh_mm.format(m.getTimeBucket()),
                            Collectors.toMap(UserInterfaceTrafficMetrics::getInterfaceInfoId, m -> m, (a, b) -> a)
                    ));

            // 构造时间-预测流量映射
            Map<String, Map<Long, UserInterfaceTrafficForecast>> forecastMap = forecastData.stream()
                    .collect(Collectors.groupingBy(
                            m -> sdf_hh_mm.format(m.getForecastTime()),
                            Collectors.toMap(UserInterfaceTrafficForecast::getInterfaceInfoId, m -> m, (a, b) ->a)
                    ));

            // 获取所有涉及的接口ID
            Set<Long> allInterfaceIds = new HashSet<>();
            actualData.forEach(a->allInterfaceIds.add(a.getInterfaceInfoId()));
            forecastData.forEach(f->allInterfaceIds.add(f.getInterfaceInfoId()));

            // 查询接口信息
            Map<Long,InterfaceInfo> interfaceInfoMap=new HashMap<>();
            if(!allInterfaceIds.isEmpty()){
                LambdaQueryWrapper<InterfaceInfo> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.in(InterfaceInfo::getId,allInterfaceIds);
                queryWrapper.select(InterfaceInfo::getId,InterfaceInfo::getName);
                List<InterfaceInfo> interfaceInfos = interfaceInfoService.list(queryWrapper);
                interfaceInfoMap=interfaceInfos.stream()
                        .collect(Collectors.toMap(InterfaceInfo::getId,i->i));
            }

            // 遍历所有时间点和接口，构造VO
            for (String timeLabel : actualMap.keySet()) {
                Map<Long, UserInterfaceTrafficMetrics> actualAtTime = actualMap.get(timeLabel);
                Map<Long, UserInterfaceTrafficForecast> forecastAtTime = forecastMap.getOrDefault(timeLabel, new HashMap<>());

                for (Map.Entry<Long, UserInterfaceTrafficMetrics> entry : actualAtTime.entrySet()) {
                    Long iid = entry.getKey();
                    UserInterfaceTrafficMetrics actual = entry.getValue();
                    UserInterfaceTrafficForecast forecast = forecastAtTime.get(iid);
                    InterfaceInfo info = interfaceInfoMap.get(iid);
                    if(info==null) continue;

                    TrafficForecastVo vo = new TrafficForecastVo();
                    vo.setInterfaceInfoId(iid);
                    vo.setTimeLabel(timeLabel);
                    vo.setActualRequestCount(actual.getRequestCount());
                    vo.setAvgLatency(actual.getAvgLatencyMs());

                    // 计算成功率
                    if(actual.getRequestCount()>0){
                        double successRate=(actual.getSuccessCount()*100.0)/actual.getRequestCount();
                        vo.setSuccessRate(BigDecimal.valueOf(successRate).setScale(2,RoundingMode.HALF_UP).doubleValue());
                    }

                    // 填充接口名称
                    vo.setInterfaceName(info.getName());

                    // 填充预测数据
                    if(forecast!=null){
                        vo.setPredictedRequestCount(forecast.getForecastRequestCount());
                        vo.setConfidenceUpper(forecast.getConfidenceUpper());
                        vo.setConfidenceLower(forecast.getConfidenceLower());
                        vo.setModelType(forecast.getModelType());
                    }
                    result.add(vo);
                }

            }
        }else{
            if(AnalysisTypeEnum.all.getType().equals(type)&&!userService.isAdmin(request)){
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
            }else if(interfaceId!=null&&!interfaceInfoService.isInfo(userId,interfaceId)){
                throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"当前用户未上传过此接口");
            }


            // 2. 查询实际流量
            LambdaQueryWrapper<InterfaceTrafficMetrics> metricsLambdaQueryWrapper = new LambdaQueryWrapper<>();
            if(interfaceId!=null){
                metricsLambdaQueryWrapper.eq(InterfaceTrafficMetrics::getInterfaceInfoId,interfaceId);
            }
            metricsLambdaQueryWrapper.between(InterfaceTrafficMetrics::getTimeBucket,
                    Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),
                    Date.from(now.atZone(ZoneId.systemDefault()).toInstant())
            );
            metricsLambdaQueryWrapper.orderByDesc(InterfaceTrafficMetrics::getTimeBucket);
            List<InterfaceTrafficMetrics> actualData = metricsService.list(metricsLambdaQueryWrapper);

            // 3. 查询预测数据
            LambdaQueryWrapper<InterfaceTrafficForecast> forecastLambdaQueryWrapper = new LambdaQueryWrapper<>();
            if(interfaceId!=null){
                forecastLambdaQueryWrapper.eq(InterfaceTrafficForecast::getInterfaceInfoId,interfaceId);
            }
            forecastLambdaQueryWrapper.between(InterfaceTrafficForecast::getForecastTime,
                    Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),
                    Date.from(now.atZone(ZoneId.systemDefault()).toInstant())
            );
            forecastLambdaQueryWrapper.orderByDesc(InterfaceTrafficForecast::getForecastTime);
            List<InterfaceTrafficForecast> forecastData = forecastService.list(forecastLambdaQueryWrapper);



            // 构造时间-实际流量映射
            Map<String, Map<Long, InterfaceTrafficMetrics>> actualMap = actualData.stream()
                    .collect(Collectors.groupingBy(
                            m -> sdf_hh_mm.format(m.getTimeBucket()),
                            Collectors.toMap(InterfaceTrafficMetrics::getInterfaceInfoId, m -> m, (a, b) -> a)
                    ));

            // 构造时间-预测流量映射
            Map<String, Map<Long, InterfaceTrafficForecast>> forecastMap = forecastData.stream()
                    .collect(Collectors.groupingBy(
                            m -> sdf_hh_mm.format(m.getForecastTime()),
                            Collectors.toMap(InterfaceTrafficForecast::getInterfaceInfoId, m -> m, (a, b) ->a)
                    ));

            // 获取所有涉及的接口ID
            Set<Long> allInterfaceIds = new HashSet<>();
            actualData.forEach(a->allInterfaceIds.add(a.getInterfaceInfoId()));
            forecastData.forEach(f->allInterfaceIds.add(f.getInterfaceInfoId()));

            // 查询接口信息
            Map<Long,InterfaceInfo> interfaceInfoMap=new HashMap<>();
            if(!allInterfaceIds.isEmpty()){
                LambdaQueryWrapper<InterfaceInfo> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.in(InterfaceInfo::getId,allInterfaceIds);
                queryWrapper.select(InterfaceInfo::getId,InterfaceInfo::getName);
                List<InterfaceInfo> interfaceInfos = interfaceInfoService.list(queryWrapper);
                interfaceInfoMap=interfaceInfos.stream()
                        .collect(Collectors.toMap(InterfaceInfo::getId,i->i));
            }

            // 遍历所有时间点和接口，构造VO
            for (String timeLabel : actualMap.keySet()) {
                Map<Long, InterfaceTrafficMetrics> actualAtTime = actualMap.get(timeLabel);
                Map<Long, InterfaceTrafficForecast> forecastAtTime = forecastMap.getOrDefault(timeLabel, new HashMap<>());

                for (Map.Entry<Long, InterfaceTrafficMetrics> entry : actualAtTime.entrySet()) {
                    Long iid = entry.getKey();
                    InterfaceTrafficMetrics actual = entry.getValue();
                    InterfaceTrafficForecast forecast = forecastAtTime.get(iid);
                    InterfaceInfo info = interfaceInfoMap.get(iid);
                    if(info==null) continue;

                    TrafficForecastVo vo = new TrafficForecastVo();
                    vo.setInterfaceInfoId(iid);
                    vo.setTimeLabel(timeLabel);
                    vo.setActualRequestCount(actual.getRequestCount());
                    vo.setAvgLatency(actual.getAvgLatencyMs());

                    // 计算成功率
                    if(actual.getRequestCount()>0){
                        double successRate=(actual.getSuccessCount()*100.0)/actual.getRequestCount();
                        vo.setSuccessRate(BigDecimal.valueOf(successRate).setScale(2,RoundingMode.HALF_UP).doubleValue());
                    }

                    // 填充接口名称
                    vo.setInterfaceName(info.getName());

                    // 填充预测数据
                    if(forecast!=null){
                        vo.setPredictedRequestCount(forecast.getForecastRequestCount());
                        vo.setConfidenceUpper(forecast.getConfidenceUpper());
                        vo.setConfidenceLower(forecast.getConfidenceLower());
                        vo.setModelType(forecast.getModelType());
                    }
                    result.add(vo);
                }

            }
        }


        return ResultUtils.success(result);

    }

    /**
     * 构造图表数据
     *
     * @param interfaceInfo 接口信息
     * @param historicalData 历史数据
     * @param forecastData 预测数据
     * @param includeConfidence 是否包含置信区间
     * @return 图表VO
     */
    private TrafficForecastChartVO buildChartData(InterfaceInfo interfaceInfo,
                                                  List<InterfaceTrafficMetrics> historicalData,
                                                  List<InterfaceTrafficForecast> forecastData,
                                                  boolean includeConfidence
                                                  ){
        TrafficForecastChartVO chartVO = new TrafficForecastChartVO();

        // 1. 设置接口基本信息
        chartVO.setInterfaceId(interfaceInfo.getId());
        chartVO.setInterfaceName(interfaceInfo.getName());
        chartVO.setPath(interfaceInfo.getUrl());
        chartVO.setMethod(interfaceInfo.getMethod());

        // 2. 初始化数据列表
        List<String> timeLabels = new ArrayList<>();
        List<Integer> actualValues = new ArrayList<>();
        List<Integer> predictedValues = new ArrayList<>();
        List<Integer> confidenceLower = new ArrayList<>();
        List<Integer> confidenceUpper = new ArrayList<>();


        // 3. 填充历史数据
        for (InterfaceTrafficMetrics metrics : historicalData) {
            timeLabels.add(sdf.format(metrics.getTimeBucket()));
            actualValues.add(metrics.getRequestCount());
            predictedValues.add(null); // 历史部分预测值为null
            if(includeConfidence){
                confidenceLower.add(null);
                confidenceUpper.add(null);
            }
        }

        // 记录分界点索引（历史数据和预测数据的分界）
        int splitIndex = timeLabels.size();
        chartVO.setSplitIndex(splitIndex);

        // 4. 填充预测数据
        for (InterfaceTrafficForecast forecast : forecastData) {
            timeLabels.add(sdf.format(forecast.getForecastTime()));
            actualValues.add(null);// 预测部分实际值为null
            predictedValues.add(forecast.getForecastRequestCount());
            if (includeConfidence) {
                confidenceLower.add(forecast.getConfidenceLower());
                confidenceUpper.add(forecast.getConfidenceUpper());
            }
            //记录模型信息（取最后一条）
            chartVO.setMethod(forecast.getModelType());
            if(forecast.getAccuracyScore()!=null){
                chartVO.setAccuracyScore(forecast.getAccuracyScore().toString());
            }
        }

        // 5. 设置图表数据
        chartVO.setTimeLabels(timeLabels);
        chartVO.setActualValues(actualValues);
        chartVO.setPredictedValues(predictedValues);
        if(includeConfidence){
            chartVO.setConfidenceLower(confidenceLower);
            chartVO.setConfidenceUpper(confidenceUpper);
        }

        // 6. 计算统计摘要
        TrafficForecastChartVO.TrafficSummary summary = new TrafficForecastChartVO.TrafficSummary();

        //历史平均
        double avgHistorical = actualValues.stream()
                .filter(Objects::nonNull)
                .mapToInt(Integer::intValue)
                .average()
                .orElse(0.0);
        summary.setAvgHistorical(BigDecimal.valueOf(avgHistorical).setScale(2, RoundingMode.HALF_UP).doubleValue());

        // 预测平均
        double avgForecast = predictedValues.stream()
                .filter(Objects::nonNull)
                .mapToInt(Integer::intValue)
                .average()
                .orElse(0.0);
        summary.setAvgForecast(BigDecimal.valueOf(avgForecast).setScale(2, RoundingMode.HALF_UP).doubleValue());

        // 增长率 ,公式：增长率 = (（期末值 - 期初值） / 期初值) × 100%
        if(avgHistorical>0){
            double growthRate=((avgForecast-avgHistorical)/avgHistorical)*100;
            summary.setAvgForecast(BigDecimal.valueOf(growthRate).setScale(2, RoundingMode.HALF_UP).doubleValue());
        }

        // 历史最大值
        int maxHistorical = actualValues.stream()
                .filter(Objects::nonNull)
                .mapToInt(Integer::intValue)
                .max()
                .orElse(0);
        summary.setMaxHistorical(maxHistorical);

        // 预测最大值及峰值时间
        int maxForecast = 0;
        int maxIndex = -1;
        for (int i = 0; i < predictedValues.size(); i++) {
            Integer val = predictedValues.get(i);
            if (val != null && val > maxForecast) {
                maxForecast = val;
                maxIndex = i;
            }
        }
        summary.setMaxForecast(maxForecast);
        if(maxIndex>=0&&maxIndex<timeLabels.size()){
            summary.setPeakTime(timeLabels.get(maxIndex));
        }

        chartVO.setSummary(summary);

        return chartVO;
    }



    /**
     * 构造图表数据
     *
     * @param interfaceInfo 接口信息
     * @param historicalData 历史数据
     * @param forecastData 预测数据
     * @param includeConfidence 是否包含置信区间
     * @return 图表VO
     */
    private TrafficForecastChartVO buildUserInterfaceChartData(InterfaceInfo interfaceInfo,
                                                  List<UserInterfaceTrafficMetrics> historicalData,
                                                  List<UserInterfaceTrafficForecast> forecastData,
                                                  boolean includeConfidence
    ){
        TrafficForecastChartVO chartVO = new TrafficForecastChartVO();

        // 1. 设置接口基本信息
        chartVO.setInterfaceId(interfaceInfo.getId());
        chartVO.setInterfaceName(interfaceInfo.getName());
        chartVO.setPath(interfaceInfo.getUrl());
        chartVO.setMethod(interfaceInfo.getMethod());

        // 2. 初始化数据列表
        List<String> timeLabels = new ArrayList<>();
        List<Integer> actualValues = new ArrayList<>();
        List<Integer> predictedValues = new ArrayList<>();
        List<Integer> confidenceLower = new ArrayList<>();
        List<Integer> confidenceUpper = new ArrayList<>();


        // 3. 填充历史数据
        for (UserInterfaceTrafficMetrics metrics : historicalData) {
            timeLabels.add(sdf.format(metrics.getTimeBucket()));
            actualValues.add(metrics.getRequestCount());
            predictedValues.add(null); // 历史部分预测值为null
            if(includeConfidence){
                confidenceLower.add(null);
                confidenceUpper.add(null);
            }
        }

        // 记录分界点索引（历史数据和预测数据的分界）
        int splitIndex = timeLabels.size();
        chartVO.setSplitIndex(splitIndex);

        // 4. 填充预测数据
        for (UserInterfaceTrafficForecast forecast : forecastData) {
            timeLabels.add(sdf.format(forecast.getForecastTime()));
            actualValues.add(null);// 预测部分实际值为null
            predictedValues.add(forecast.getForecastRequestCount());
            if (includeConfidence) {
                confidenceLower.add(forecast.getConfidenceLower());
                confidenceUpper.add(forecast.getConfidenceUpper());
            }
            //记录模型信息（取最后一条）
            chartVO.setMethod(forecast.getModelType());
            if(forecast.getAccuracyScore()!=null){
                chartVO.setAccuracyScore(forecast.getAccuracyScore().toString());
            }
        }

        // 5. 设置图表数据
        chartVO.setTimeLabels(timeLabels);
        chartVO.setActualValues(actualValues);
        chartVO.setPredictedValues(predictedValues);
        if(includeConfidence){
            chartVO.setConfidenceLower(confidenceLower);
            chartVO.setConfidenceUpper(confidenceUpper);
        }

        // 6. 计算统计摘要
        TrafficForecastChartVO.TrafficSummary summary = new TrafficForecastChartVO.TrafficSummary();

        //历史平均
        double avgHistorical = actualValues.stream()
                .filter(Objects::nonNull)
                .mapToInt(Integer::intValue)
                .average()
                .orElse(0.0);
        summary.setAvgHistorical(BigDecimal.valueOf(avgHistorical).setScale(2, RoundingMode.HALF_UP).doubleValue());

        // 预测平均
        double avgForecast = predictedValues.stream()
                .filter(Objects::nonNull)
                .mapToInt(Integer::intValue)
                .average()
                .orElse(0.0);
        summary.setAvgForecast(BigDecimal.valueOf(avgForecast).setScale(2, RoundingMode.HALF_UP).doubleValue());

        // 增长率 ,公式：增长率 = (（期末值 - 期初值） / 期初值) × 100%
        if(avgHistorical>0){
            double growthRate=((avgForecast-avgHistorical)/avgHistorical)*100;
            summary.setAvgForecast(BigDecimal.valueOf(growthRate).setScale(2, RoundingMode.HALF_UP).doubleValue());
        }

        // 历史最大值
        int maxHistorical = actualValues.stream()
                .filter(Objects::nonNull)
                .mapToInt(Integer::intValue)
                .max()
                .orElse(0);
        summary.setMaxHistorical(maxHistorical);

        // 预测最大值及峰值时间
        int maxForecast = 0;
        int maxIndex = -1;
        for (int i = 0; i < predictedValues.size(); i++) {
            Integer val = predictedValues.get(i);
            if (val != null && val > maxForecast) {
                maxForecast = val;
                maxIndex = i;
            }
        }
        summary.setMaxForecast(maxForecast);
        if(maxIndex>=0&&maxIndex<timeLabels.size()){
            summary.setPeakTime(timeLabels.get(maxIndex));
        }

        chartVO.setSummary(summary);

        return chartVO;
    }


    @Getter
    public enum AnalysisTypeEnum{
        all(0,"all"),
        upload(1,"upload" ),
        use(2,"use");

        private Integer type;
        private String description;

        AnalysisTypeEnum(int i, String description) {
            this.type=i;
            this.description=description;
        }


        public static AnalysisTypeEnum get(int i){
            for (AnalysisTypeEnum value : values()) {
                if(value.type==i) return  value;
            }
            return null;
        }

    }
}
